package com.yxx.service.Impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxx.entity.Article;
import com.yxx.entity.Category;
import com.yxx.entityModel.vo.Result.PageResult;
import com.yxx.entityModel.vo.query.ArticleConditionQuery;
import com.yxx.entityModel.vo.query.CategoryQuery;
import com.yxx.entityModel.vo.request.CategoryRequest;
import com.yxx.entityModel.vo.response.*;
import com.yxx.mapper.ArticleMapper;
import com.yxx.mapper.CategoryMapper;
import com.yxx.service.CategoryService;
import com.yxx.utils.BeanCopyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yuxiangxun
 * @date 2025/2/3
 * @apiNote
 */
@Service
@Slf4j
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private ArticleMapper articleMapper;

    private static final int maxDeep = 3;


    @Override
    public PageResult<CategoryBackResponse> categoryBackResponseList(CategoryQuery categoryQuery) {
        // 查询分类数量
        Long count = categoryMapper.selectCount(new LambdaQueryWrapper<Category>()
                .like(StringUtils.hasText(categoryQuery.getKeyword()), Category::getCategoryName,
                        categoryQuery.getKeyword()));
        if (count == 0) {
            return new PageResult<>();
        }
        // 分页查询分类列表
        List<CategoryBackResponse> categoryList = categoryMapper.selectCategoryBackList(categoryQuery);

        // 分类id集合
        Set<Integer> categoryByIdList = categoryList.stream()
                .map(CategoryBackResponse::getId)
                .collect(Collectors.toSet());
        // 后台分类列表递归  这里可能循环引用导致溢出了 重新写一下这里的业务逻辑 (修改bug成功)
        List<CategoryBackResponse> categoryBackResponseList = categoryList.stream()
                .map(category -> {
                    // 思路： 获取每个分类的父id，如果该id没有在分类id集合中，从此id开始最为递归开始节点  根id参数为1，这里拿到根id都是1
                    // 获取每个分类的父id
                    Integer parentId = category.getParentId();
                    if(false == categoryByIdList.contains(parentId)){
                        categoryByIdList.add(parentId);
                        return recurCategoryList(categoryList, parentId, 0, maxDeep);
                    }
                    return new ArrayList<CategoryBackResponse>();
                })
                .collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);

        // 执行分页
        int fromIndex = categoryQuery.getCurrent();
        int size = categoryQuery.getSize();
        int toIndex = categoryList.size() - fromIndex > size ? fromIndex + size : categoryList.size();
        return new PageResult<>(categoryBackResponseList.subList(fromIndex,toIndex), (long) categoryBackResponseList.size());
    }



    /**
     * 递归生成分类列表
     * @param categoryList
     * @param parentId
     * @param currentDeep
     * @param maxDeep
     * @return
     */
    private List<CategoryBackResponse> recurCategoryList(List<CategoryBackResponse> categoryList, Integer parentId, int currentDeep, int maxDeep) {
        List<CategoryBackResponse> tree = new ArrayList<>();
        if (maxDeep < 0) {
            return tree;
        }
        if (currentDeep == maxDeep) {
            return tree;
        } else {
            for (CategoryBackResponse category : categoryList) {
                if (category.getParentId().equals(parentId)) {
                    category.setChildren(recurCategoryList(categoryList, category.getId(), currentDeep + 1, maxDeep));
                    tree.add(category);
                }
            }
        }
        return tree;
    }


    /**
     * 添加分类
     * @param categoryRequest
     */
    @Override
    public void addCategory(CategoryRequest categoryRequest) {
        // 查询请求中的分类名称是否在数据库中存在
        Category existCategory = categoryMapper.selectOne(new LambdaQueryWrapper<Category>()
                .select(Category::getId)
                .eq(Category::getCategoryName, categoryRequest.getCategoryName())
        );
        // 如果存在，断言，显示“分类名已存在”，无法执行下面的逻辑
        Assert.isNull(existCategory,categoryRequest.getCategoryName()+"分类名已存在");
        // 添加分类
        Category newCategory = Category.builder()
                .id(categoryRequest.getId())
                .categoryName(categoryRequest.getCategoryName())
                .build();
        baseMapper.insert(newCategory);
    }

    /**
     * 删除分类
     * @param categoryIdList
     */
    @Override
    public void deleteCategory(List<Integer> categoryIdList) {
        // 查看分类下是否有文章，查询出分类数量即可
        Long count = articleMapper.selectCount(new LambdaQueryWrapper<Article>()
                .in(Article::getCategoryId, categoryIdList)
        );
        // 断言，有文章，无法删除
        Assert.isFalse(count > 0, "删除失败，分类下存在文章");
        // 批量删除分类
        baseMapper.deleteBatchIds(categoryIdList);
    }

    /**
     * 修改分类
     * @param category
     */
    @Override
    public void updateCategory(CategoryRequest category) {
        // 查看分类是否存在，根据分类名称 查询 分类信息
        Category existCategory = categoryMapper.selectOne(new LambdaQueryWrapper<Category>()
                .select(Category::getId)
                .eq(Category::getCategoryName,category.getCategoryName())
        );
        // 断言，修改中的分类id与数据库的分类id相同且请求中修改的分类名称和数据中存在的分类名称一样，抛异常，无法执行下面的逻辑
        Assert.isFalse(Objects.nonNull(existCategory) && !existCategory.getId().equals(category.getId()));
        // 修改分类
        Category newCategory = Category.builder()
                .id(category.getId())
                .categoryName(category.getCategoryName())
                .build();
        // 修改分类(请求修改中的id与数据库中对应信息的id一直且修改的姓名不存在)
        baseMapper.updateById(newCategory);
    }

    /**
     * 查看分类选项
     * @return
     */
    @Override
    public List<CategoryOptionResponse> categoryOptionList() {
        // 查询分类
        List<Category> categoryList = categoryMapper.selectList(new LambdaQueryWrapper<Category>()
                .orderByDesc(Category::getId));
        // 对象转换后返回
        return BeanCopyUtils.copyBeanList(categoryList,CategoryOptionResponse.class);
    }

    /**
     * 查看分类列表
     * @return
     */
    @Override
    public List<CategoryResponse> categoryListVO() {
        return categoryMapper.selectCategoryVO();
    }

    /**
     * 查看分类下的文章
     * @param articleConditionQuery
     * @return
     */
    @Override
    public ArticleConditionListResponse articleCategoryList(ArticleConditionQuery articleConditionQuery) {
        // 查询该分类下的文章、分类、标签信息
        List<ArticleConditionResponse> articleConditionResponseList= articleMapper.selectArrticleListByCondition(articleConditionQuery);
        String name = categoryMapper.selectOne(new LambdaQueryWrapper<Category>()
                .select(Category::getCategoryName)
                .eq(Category::getId, articleConditionQuery.getCategoryId())
        ).getCategoryName();
        // 封装文章列表后返回
        return ArticleConditionListResponse.builder()
                .name(name)
                .articleConditionVOList(articleConditionResponseList)
                .build();
    }


}
